#ifndef MASTERPOS_CONTEXT_PARAMS3_HPP
#define MASTERPOS_CONTEXT_PARAMS3_HPP

SJR_NAMESPACE_BEGIN

class EpubContextParams3 : public EpubContextParams2 {
public:
  constexpr static int BLOCK_SIZE = 16;

  EpubContextParams3()
      : EpubContextParams2(), mComponentA(), mComponentB(), mComponentC(), mZmk() {}

  void setZmkComponentA(unsigned char const *in, int inLen) {
    mComponentA.resize(inLen);
    memcpy(&mComponentA[0], in, inLen);
  }

  void setZmkComponentB(unsigned char const *in, int inLen) {
    mComponentB.resize(inLen);
    memcpy(&mComponentB[0], in, inLen);
  }

  void setZmkComponentC(unsigned char const *in, int inLen) {
    mComponentC.resize(inLen);
    memcpy(&mComponentC[0], in, inLen);
  }

  void cleanZmk() {
    mComponentA.clear();
    mComponentB.clear();
    mComponentC.clear();
    mZmk.clear();
  }

  void setZmk(unsigned char const *in, int inLen) {
    mZmk.resize(inLen);
    memcpy(&mZmk[0], in, inLen);
  }

  auto zmk() -> std::vector<unsigned char> & {
    if (!mZmk.empty())
      return mZmk;
    if (mComponentA.empty() || mComponentB.empty())
      return mZmk;

    mZmk.resize(BLOCK_SIZE);
    for (int i = 0; i < BLOCK_SIZE; ++i)
      mZmk[i] = mComponentA[i] ^ mComponentB[i];

    if (!mComponentC.empty()) {
      for (int i = 0; i < BLOCK_SIZE; ++i)
        mZmk[i] ^= mComponentC[i];
    }

    return mZmk;
  }

private:
  std::vector<unsigned char> mComponentA;
  std::vector<unsigned char> mComponentB;
  std::vector<unsigned char> mComponentC;

  std::vector<unsigned char> mZmk;
};

SJR_NAMESPACE_END

#endif//MASTERPOS_CONTEXT_PARAMS3_HPP
